/**
 * 导入rsbuild相关模块
 */
import { defineConfig } from '@rsbuild/core';

/**
 * 导入rsbuild插件
 */
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginVue } from '@rsbuild/plugin-vue';
import { pluginImageCompress } from '@rsbuild/plugin-image-compress';

/**
 * 自动导入插件
 */
import AutoImport from 'unplugin-auto-import/rspack';
import Components from 'unplugin-vue-components/rspack';
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';

/**
 * gzip压缩插件
 */
import CompressionPlugin from 'compression-webpack-plugin';

/**
 * 导入node模块
 */
import { resolve } from 'path';

/**
 * 导入配置文件
 */
import rsbuildPageConfig from './page.config.mjs';

/**
 * 导入类型声明
 */
import type { RsbuildConfig } from '@rsbuild/core';

/**
 * 当前时间戳
 */
const currentTimeStamp: number = new Date().getTime();

/**
 * 获取js列表
 * @param env
 * @returns
 */
const getScriptList = (env: string): Array<string> => {
  const list: Array<string> = rsbuildPageConfig.scriptList;
  const envList: Array<string> = rsbuildPageConfig.envScriptList[env];
  const totalList: Array<string> = list.concat(envList);
  return totalList.map((item: string) => {
    return `${item}?t=${currentTimeStamp}`;
  });
};

/**
 * 获取css列表
 * @param env
 * @returns
 */
const getCssList = (env: string): Array<string> => {
  const list: Array<string> = rsbuildPageConfig.cssList;
  const envList: Array<string> = rsbuildPageConfig.envCssList[env];
  const totalList: Array<string> = list.concat(envList);
  return totalList.map((item: string) => {
    return `${item}?t=${currentTimeStamp}`;
  });
};

/**
 * 获取html标题
 * @returns
 */
const getHtmlTitle = (): string => {
  return rsbuildPageConfig.title;
};

/**
 * 导出配置
 */
export default defineConfig(({ envMode }) => {
  /**
   * 获取运行环境变量
   */
  const nodeEnv: string = process.env.NODE_ENV || 'development';
  console.log('当前运行环境变量为：', envMode);

  /**
   * 获取环境变量
   */
  const env: string = process.env.APP_ENV || 'development';
  console.log('当前环境变量为：', env);

  const rsConfig: RsbuildConfig = {
    /**
     *  配置源代码相关设置
     */
    source: {
      entry: {
        index: resolve(process.cwd(), './src/index.ts'),
      },
      define: {
        'process.env.APP_ENV': JSON.stringify(process.env.APP_ENV),
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      },
      include: [
        resolve(process.cwd(), './src'),
        resolve(process.cwd(), './node_modules'),
      ],
    },

    /**
     * 配置输出相关设置
     */
    output: {
      polyfill: 'entry',
      assetPrefix: '/',
      cleanDistPath: true,
      distPath: {
        root: resolve(process.cwd(), './dist'),
        css: 'css',
        cssAsync: 'css',
        js: 'js',
        jsAsync: 'js',
        font: 'font',
        image: 'images',
      },
      filenameHash: true,
      filename: {
        css:
          nodeEnv == 'development'
            ? '[name].css'
            : '[name]-[contenthash:8].css',
        js:
          nodeEnv == 'development' ? '[name].js' : '[name]-[contenthash:8].js',
        image: '[hash][ext][query]',
        font: '[name][ext]',
      },
    },

    /**
     * 配置路径别名
     */
    resolve: {
      extensions: ['.vue', '.js', '.ts', '.less', '.css', '.mjs'],
      alias: {
        '@': resolve(process.cwd(), './src'),
      },
    },

    /**
     * 配置使用的插件
     */
    plugins: [pluginVue(), pluginLess(), pluginImageCompress()],

    /**
     * 配置工具链
     */
    tools: {
      cssExtract: {
        loaderOptions: {
          publicPath: '../',
        },
        pluginOptions: {
          ignoreOrder: true,
        },
      },
      rspack: {
        plugins: [
          AutoImport({
            imports: ['vue', 'vue-router', 'pinia'],
            resolvers: [NaiveUiResolver()],
            dts: resolve(process.cwd(), './auto-imports.d.ts'),
          }),
          Components({
            dirs: [resolve(process.cwd(), './src/components')],
            resolvers: [NaiveUiResolver()],
            dts: resolve(process.cwd(), './components.d.ts'),
          }),
          new CompressionPlugin({
            test: /\.(js|css)$/,
            filename: '[path][base].gz',
            algorithm: 'gzip',
            threshold: 10240,
            minRatio: 0.8,
          }),
        ],
      },
    },

    /**
     * 配置 HTML 相关设置
     */
    html: {
      template: resolve(process.cwd(), './index.html'),
      title: getHtmlTitle(),
      templateParameters: () => {
        return {
          js: getScriptList(env),
          css: getCssList(env),
          version: new Date().getTime(),
        };
      },
    },

    /**
     * 配置服务端相关设置
     */
    server: {
      port: 8080,
      compress: nodeEnv === 'development' ? false : true,
      open: true,
    },

    /**
     * 开发环境相关设置
     */
    dev: {
      hmr: true,
      progressBar: true,
    },

    /**
     * 性能配置，包括代码分割策略
     */
    performance: {
      chunkSplit: {
        strategy: 'custom',
        splitChunks: {
          chunks: 'all',
          maxInitialRequests: 6,
          minSize: 20000,
          maxSize: 200000,
          cacheGroups: {
            vueCore: {
              test: /[\\/]node_modules[\\/](vue|@vue\/.*|vue-router)[\\/]/,
              name: 'vue-core',
              chunks: 'all',
              priority: 40,
              enforce: true,
            },
            stateLib: {
              test: /[\\/]node_modules[\\/](pinia)[\\/]/,
              name: 'libs',
              chunks: 'all',
              priority: 25,
            },
            uiLibrary: {
              test: /[\\/]node_modules[\\/](naive-ui)[\\/]/,
              name: 'ui-lib',
              chunks: 'all',
              priority: 20,
            },
            commonComponents: {
              test: /src[\\/]components[\\/]/,
              name: 'components',
              chunks: 'async',
              minSize: 30000,
              reuseExistingChunk: true,
            },
            utilities: {
              test: /[\\/]node_modules[\\/](dayjs|axios|es-toolkit)[\\/]/,
              name: 'utils',
              chunks: 'all',
              priority: 15,
            },
            businessCode: {
              test: /src[\\/](views|stores|api)/,
              name: 'business',
              chunks: 'async',
              minChunks: 2,
              priority: 10,
            },
          },
        },
      },
    },
  };
  return rsConfig;
});
